#include base
#include bool
#include lists

(defmacro assert (id (:rest body))
  (let (($result (fresh)))
    `(let ((,$result (seq ,@body)))
       (if (= (type-of ,$result) 'boolean)
	   (if ,$result
	       'success
	     (abort ',id 
		    'expected-true		    
		    ',body))
	 (abort ',id
		'expected-boolean
		',body
		,$result)))))


(defmacro assert-false (id (:rest body))
  `(assert id (not (seq ,@body))))


(defmacro assert-eq (id x y)
  (let (($rx (fresh))
	($ry (fresh)))
    `(let ((,$rx ,x)
	   (,$ry ,y))
       (if (= ,$rx ,$ry)
	   'success
	 (abort ',id
		'expected-equality
		,$rx
		,$ry)))))

(defmacro assert-neq (id x y)
  (let (($rx (fresh))
	($ry (fresh)))
    `(let ((,$rx ,x)
	   (,$ry ,y))
       (if (not (= ,$rx ,$ry))
	   'success
	 (abort ',id
		'expected-inequality
		,$rx
		,$ry)))))

(defmacro sandbox (id (:rest body))
  `(assert ,id (all? successful-trace? (traces (seq ,@body)))))
